#include "cpppython.hpp"

using dynamic::python::wrap_pyobject;


wrap_pyobject::wrap_pyobject(PyObject * obj) : m_object(obj) 
{ 
}


var_cmp_index wrap_pyobject::comparison_index()
{
	return cmp_python;
}


void * wrap_pyobject::as_ptr() 
{ 
	return m_object; 
}


wrap_pyobject::wrap_pyobject(const wrap_pyobject & other) : m_object(other.m_object)
{
	Py_INCREF(m_object);
}


wrap_pyobject & wrap_pyobject::operator=(wrap_pyobject other)
{
	swap(other);
	return *this;
}


wrap_pyobject::~wrap_pyobject()
{
	Py_DECREF(m_object);
}


void wrap_pyobject::swap(wrap_pyobject & other)
{
	std::swap(m_object, other.m_object);
}


void wrap_pyobject::copy_to(void * dest) const
{
	new(dest) wrap_pyobject(*this);
}


var wrap_pyobject::clone()
{
	return var(*this, var::assign_impl());
}


std::string wrap_pyobject::class_name() 
{ 
	return "PyObject"; 
}


bool wrap_pyobject::as_bool() 
{
	return PyObject_IsTrue(m_object)!=0;
}


int wrap_pyobject::as_int()
{
	return PyInt_AsLong(m_object);
}


double wrap_pyobject::as_double()
{
	return PyFloat_AsDouble(m_object);
}


void wrap_pyobject::output(ostream & os)
{
	wrap_pyobject rep(PyObject_Str(m_object));
	os << PyString_AsString(rep.m_object);
}


void wrap_pyobject::output(wostream & os)
{
	char * result = PyString_AsString(m_object);
	for(char * str = result; str && *str; ++str)
		os << wchar_t(*str);
}


var wrap_pyobject::call()
{
	return py_to_var( PyObject_CallFunctionObjArgs( m_object, NULL ) );
}


var wrap_pyobject::call(const var & a0)
{
	return py_to_var( PyObject_CallFunctionObjArgs( m_object, var_to_py(a0), NULL ) );
}


var dynamic::python::py_to_var(PyObject * py)
{
	if(!py) return null;

	if(py->ob_type == &var_type)
	{
		return ((wrap_var*)py)->m_value;
	}

	return var( wrap_pyobject(py), var::assign_impl() );
}

var wrap_pyobject::op_add(const var & a)
{
	var ret = py_to_var(PyNumber_Add(m_object, var_to_py(a)));
	throw_exceptions();
	return ret;
}
